package org.cboard.redis;

import org.cboard.dataprovider.DataProvider;
import org.cboard.dataprovider.Initializing;
import org.cboard.dataprovider.aggregator.Aggregatable;
import org.cboard.dataprovider.annotation.DatasourceParameter;
import org.cboard.dataprovider.annotation.ProviderName;
import org.cboard.dataprovider.annotation.QueryParameter;
import org.cboard.dataprovider.config.AggConfig;
import org.cboard.dataprovider.config.DimensionConfig;
import org.cboard.dataprovider.result.AggregateResult;
import org.cboard.dataprovider.result.ColumnIndex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import redis.clients.jedis.Jedis;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * redis 数据源提供类
 */
@ProviderName(name = "Redis")
public class RedisDataProvider extends DataProvider implements Aggregatable/*, Initializing*/ {

    private static final Logger LOG = LoggerFactory.getLogger(RedisDataProvider.class);

  /*  @Autowired
    private JedisUtil.Keys jedisKeys;
    @Autowired
    private JedisUtil.Strings jedisStrings;*/

    @Value("${dataprovider.resultLimit:300000}")
    private int resultLimit;

    private String[] columns;


    @DatasourceParameter(label = "{{'DATAPROVIDER.REDIS.HOST'|translate}} *",
            type = DatasourceParameter.Type.Input,
            required = true,
            order = 1)
    private String HOST = "host";
    @DatasourceParameter(label = "{{'DATAPROVIDER.REDIS.PORT'|translate}} *",
            type = DatasourceParameter.Type.Input,
            required = true,
            order = 2)
    private String PORT = "port";
    @DatasourceParameter(label = "{{'DATAPROVIDER.REDIS.DB_INDEX'|translate}} *",
            options = {"0",
                    "1",
                    "2",
                    "3",
                    "4",
                    "5",
                    "6",
                    "7",
                    "8",
                    "9",
                    "10",
                    "11",
                    "12",
                    "13",
                    "14",
                    "15"},
            type = DatasourceParameter.Type.Select,
            required = true,
            order = 3)
    private String DBINDEX = "dbindex";
    @QueryParameter(label = "{{'DATAPROVIDER.REDIS.KEY'|translate}}",
            type = QueryParameter.Type.Input,
            required = true,
            order = 4)
    private String KEY = "key";

    @Override
    public boolean doAggregationInDataSource() {
        return true;
    }

    /**
     * 待研究
     * @return
     * @throws Exception
     */
    @Override
    public String[][] getData() throws Exception {
        String host = dataSource.get(HOST);
        int port = Integer.parseInt(dataSource.get(PORT));
        int dbindex = Integer.parseInt(dataSource.get(DBINDEX));
        String key = query.get(KEY);

        try {
            Jedis jedis = initJedis(host, port, dbindex);
            Set<String> hkeysSet = jedis.hkeys(key);
            String[] hkeysStringArr = hkeysSet.toArray(new String[hkeysSet.size()]);
            columns = hkeysStringArr;
            String[][] strings = new String[][]{hkeysStringArr};
            System.out.println("getData(),连接成功: " + strings[0].toString());
            for (String hkey : hkeysStringArr) {
                String hget = jedis.hget(key, hkey);
                System.out.println("hkey : " + hkey + " : " + hget);
            }
            return strings;
        } catch (Exception e) {
            throw new Exception("ERROR:" + e.getMessage(), e);
        }

    }

    @Override
    public String[] queryDimVals(String columnName, AggConfig config) throws Exception {
        return new String[0];
    }

    @Override
    public String[] getColumn() throws Exception {
        try {
            Jedis jedis = initJedis(dataSource.get(HOST), Integer.parseInt(dataSource.get(PORT)), Integer.parseInt(dataSource.get(DBINDEX)));
            String key = query.get(KEY);
            Set<String> hkeysSet = jedis.hkeys(key);
            String[] hkeysStringArr = hkeysSet.toArray(new String[hkeysSet.size()]);
            columns = hkeysStringArr;
            System.out.println("getColumn()，连接成功");
            return columns;
        } catch (Exception e) {
            throw new Exception("ERROR:" + e.getMessage(), e);
        }
    }

    private Jedis initJedis(String s, int i, int i2) {
        Jedis jedis = new Jedis(s, i);
        jedis.select(i2);
        return jedis;
    }

    @Override
    public AggregateResult queryAggData(AggConfig config) throws Exception {

        LOG.info("Redis-queryAggData");

        Stream<DimensionConfig> dimStream = Stream.concat(config.getColumns().stream(), config.getRows().stream());
        List<ColumnIndex> dimensionList = dimStream.map(ColumnIndex::fromDimensionConfig).collect(Collectors.toList());
        List<ColumnIndex> valueList = config.getValues().stream().map(ColumnIndex::fromValueConfig).collect(Collectors.toList());
        List<ColumnIndex> columnList = new ArrayList<>();
        columnList.addAll(dimensionList);
        columnList.addAll(valueList);

        // 排序
        IntStream.range(0, columnList.size()).forEach(j -> columnList.get(j).setIndex(j));

        Jedis jedis = initJedis(dataSource.get(HOST), Integer.parseInt(dataSource.get(PORT)), Integer.parseInt(dataSource.get(DBINDEX)));
        String key = query.get(KEY);

        List<String[]> result = new ArrayList<>();
        for (ColumnIndex columnIndex : columnList) {
            String columns = jedis.hget(key, columnIndex.getName());
            String[] split = columns.split(",");
            result.add(split);
        }

        int insize = result.get(0).length;
        String[][] _result = new String[insize][];

        for (int i = 0; i < insize; i++) {
            String[] s = new String[result.size()];
            for (int i1 = 0; i1 < result.size(); i1++) {
                s[i1] = result.get(i1)[i];
            }
            _result[i] = s;
        }
        return new AggregateResult(columnList, _result);
    }

    @Override
    public void test() throws Exception {
        String queryStr = query.get("key");
        LOG.info("Execute query: {}", queryStr);
        String host = dataSource.get(HOST);
        int port = Integer.parseInt(dataSource.get(PORT));
        int dbindex = Integer.parseInt(dataSource.get(DBINDEX));
        try {
            Jedis jedis = initJedis(host, port, dbindex);
            System.out.println("连接成功 " + jedis.ping());
        } catch (Exception e) {
            throw new Exception("ERROR:" + e.getMessage(), e);
        }
    }

}
